﻿/*****************************************************
**Copyright(C), 2022-2023, Ciqtek Technology.
**Version:     1.0
**Author:      Barmaco
**Date:        2022/11/30
**Description: ScopeGuard 是 RAII 的一个例子，对象出了作用域会自动调用其释构函数，参考：https://zhuanlan.zhihu.com/p/21303431
** 用法：ON_SCOPE_EXIT
**      {
**        // TODO impl
**      };
** 放入函数体作用域内，出了作用域自动执行 impl实现方法
*****************************************************/

#ifndef SCOPEGUARD_H
#define SCOPEGUARD_H


#include <type_traits>

namespace Common {

	template <typename Fun>
	class ScopeGuard
	{
	public:
		/**
		 * @brief   ScopeGuard 构造函数
		 * @param   f 函数模版
		 * @return
		 */
		ScopeGuard(Fun&& f)
			: m_fun(std::forward<Fun>(f))
			, m_isActive(true)
		{
		}

		/**
		 * @brief   ~ScopeGuard 析构函数
		 * @return
		 */
		~ScopeGuard()
		{
			if (m_isActive)
			{
				m_fun();
			}
		}

		/**
		 * @brief   取消RAII自动释放
		 * @return  void
		 */
		void dismiss()
		{
			m_isActive = false;
		}

		/**
		 * @brief   ScopeGuard 移除默认构造
		 */
		ScopeGuard() = delete;

		/**
		 * @brief   ScopeGuard 移除 =
		 */
		ScopeGuard(const ScopeGuard&) = delete;

		/**
		 * @brief   ScopeGuard 移除 =
		 */
		ScopeGuard& operator=(const ScopeGuard&) = delete;

		/**
		 * @brief   ScopeGuard 移动拷贝
		 */
		ScopeGuard(ScopeGuard&& rhs) : m_fun(std::move(rhs.m_fun)), m_isActive(rhs.m_isActive)
		{
			rhs.dismiss();
		}

	private:
		/** RAII函数
		 */
		Fun m_fun;

		/** 是否激活
		 */
		bool m_isActive;
	};

	enum class ScopeGuardOnExit {};

	template <typename Fun>
	inline ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
		return ScopeGuard<Fun>(std::forward<Fun>(fn));
	}

#define SCOPEGUARD_CONCATENATE_IMPL(s1, s2) s1##s2
#define SCOPEGUARD_CONCATENATE(s1, s2) SCOPEGUARD_CONCATENATE_IMPL(s1, s2)

	/** 帮助宏
	 */
#define ON_SCOPE_EXIT \
    auto SCOPEGUARD_CONCATENATE(exitBlock, __LINE__) = ScopeGuardOnExit() + [&]()

}

#endif //SCOPEGUARD_H